package fi.foyt.cs.api.json;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.json.JSONObject;

public class EntityRendererVault {

  public static EntityRendererVault getInstance() {
    return instance;
  }
  
  private static EntityRendererVault instance = new EntityRendererVault();
  
  public EntityRendererVault() {
    registerEntityRenderer(new GeneralTaskRenderer());
    registerEntityRenderer(new GeneralTaskLevelRenderer());
    registerEntityRenderer(new SceneCategoryRenderer());
    registerEntityRenderer(new SceneRenderer());
    registerEntityRenderer(new ItemRenderer());
    registerEntityRenderer(new InventoryItemRenderer());
    registerEntityRenderer(new TaskRewardItemRenderer());
    registerEntityRenderer(new TaskRewardsRenderer());
    registerEntityRenderer(new StashedItemRenderer());
    registerEntityRenderer(new UserRenderer());
    registerEntityRenderer(new UserLocationRenderer());
  }
  
  @SuppressWarnings({ "rawtypes", "unchecked" })
  public JSONObject renderEntity(Locale locale, Object entity) {
    EntityRenderer entityRenderer = getEntityRenderer(entity.getClass());
    if (entityRenderer != null)
      return entityRenderer.getAsJson(locale, entity);
    
    return null;
  }
  
  public EntityRenderer<?> getEntityRenderer(Class<?> entityType) {
    return entityRenderers.get(entityType);
  }
  
  private void registerEntityRenderer(EntityRenderer<?> entityRenderer) {
    Class<?> entityReaderClass = entityRenderer.getClass();
    Type[] entityReaderInterfaces = entityReaderClass.getGenericInterfaces();
    for (Type entityReaderInterface : entityReaderInterfaces) {
      if (entityReaderInterface instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) entityReaderInterface;
        if (parameterizedType.getRawType().equals(EntityRenderer.class)) {
          Class<?> entityRendererType = (Class<?>) parameterizedType.getActualTypeArguments()[0];
          entityRenderers.put(entityRendererType, entityRenderer);
          return;
        }
      }
    }
  }
  
  private Map<Class<?>, EntityRenderer<?>> entityRenderers = new HashMap<Class<?>, EntityRenderer<?>>();
}
